package com.payment.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.payment.common.base.AjaxResult;
import com.payment.common.base.Const;
import com.payment.common.enums.SystemConfigCode;
import com.payment.common.support.Convert;
import com.payment.common.type.MoneyTypeStatus;
import com.payment.common.utils.Md5Utils;
import com.payment.common.utils.RedisPoolUtil;
import com.payment.common.utils.StringUtils;
import com.payment.system.domain.*;
import com.payment.system.mapper.*;
import com.payment.system.service.IAcqService;
import com.payment.system.util.GuangGuUtil;
import com.payment.system.vo.CreditCardVo;
import com.payment.system.vo.PaymentOrderVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * 通道 服务层实现
 *
 * @author payment
 * @date 2019-01-01
 */
@Service
public class AcqServiceImpl implements IAcqService {
    private static final Logger log = LoggerFactory.getLogger(IAcqService.class);

    @Autowired
    private MoneyChangeMapper moneyChangeMapper;
    @Autowired
    private AcqMapper acqMapper;
    @Autowired
    private AcqBindMapper acqBindMapper;
    @Autowired
    private PaymentOrderMapper paymentOrderMapper;
    @Autowired
    private MerchantMapper merchantMapper;
    @Autowired
    private MerchantIncreaseLimitMapper merchantIncreaseLimitMapper;
    @Autowired
    private IssBankMapper issBankMapper;
    @Autowired
    private SystemConfigMapper configMapper;
    @Autowired
    private MerchantWalletMapper merchantWalletMapper;

    /**
     * 查询通道信息
     *
     * @param id 通道ID
     * @return 通道信息
     */
    @Override
    public Acq selectAcqById(String id) {
        return acqMapper.selectAcqById(id);
    }

    /**
     * 查询通道列表
     *
     * @param acq 通道信息
     * @return 通道集合
     */
    @Override
    public List<Acq> selectAcqList(Acq acq) {
        return acqMapper.selectAcqList(acq);
    }

    /**
     * 新增通道
     *
     * @param acq 通道信息
     * @return 结果
     */
    @Override
    public AjaxResult insertAcq(Acq acq, String adminUuid) {
        List<Acq> list = acqMapper.selectAcqListByName(acq.getAcqName());
        Acq acq1 = acqMapper.selectAcqByCode(acq.getAcqCode());
        if (list.size() > 0) {
            return AjaxResult.error("通道名称已存在！");
        }
        if (StringUtils.isNotNull(acq1)) {
            return AjaxResult.error("通道编码已存在！");
        }
        acq.setId(StringUtils.randomUUID());
        // 创建人
        acq.setCreateUserId(adminUuid);
        if (acqMapper.insertAcq(acq) > 0) {
            // 添加渠道成功,判断添加的渠道是否需要签约
            if (acq.getBindType() == 1) {
                // 如果不需要签约,将所有的用户信用卡信息初始化到中间表
                List<MerchantIncreaseLimit> merchantIncreaseLimits = merchantIncreaseLimitMapper.selectAll();
                for (MerchantIncreaseLimit me : merchantIncreaseLimits) {
                    me.setAcqId(acq.getId());
                }
                // 批量插入中间表
                acqBindMapper.batchAddBind(merchantIncreaseLimits);
            }
        }

        return AjaxResult.success();
    }

    /**
     * 修改通道
     *
     * @param acq 通道信息
     * @return 结果
     */
    @Override
    public int updateAcq(Acq acq) {
        // 查询通道信息
        Acq bindType = acqMapper.selectAcqById(acq.getId());
        int i = acqMapper.updateAcq(acq);
        if (!bindType.getBindType().equals(acq.getBindType())) {
            // 批量删除
            acqBindMapper.deletByAcqId(acq.getId());
            if (acq.getBindType() == 1) {
                // 查询信用卡信息
                List<MerchantIncreaseLimit> merchantIncreaseLimits = merchantIncreaseLimitMapper.selectAll();
                for (MerchantIncreaseLimit me : merchantIncreaseLimits) {
                    me.setAcqId(acq.getId());
                }
                // 批量查询中间表
                acqBindMapper.batchAddBind(merchantIncreaseLimits);
            }

        }
        return i;
    }

    /**
     * 删除通道对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteAcqByIds(String ids) {
        return acqMapper.deleteAcqByIds(Convert.toStrArray(ids));
    }

    /**
     * 修改通道状态 启用或禁用
     *
     * @param acq
     * @param
     * @return
     */
    @Override
    public AjaxResult changeEmployStatus(Acq acq) {
        if (acq == null) {
            return AjaxResult.error("获取通道信息异常，请联系客服咨询原因！");
        }
        if (acq.getStatus().equals("10B")) {
            acq.setEndEditTime(new Date());
        }
        acqMapper.updateAcq(acq);
        return AjaxResult.success();
    }

    /**
     * 根据生效状态查询通道集合
     *
     * @param status
     * @return
     */
    @Override
    public List<Acq> selectAcqListByStatus(String status) {
        return acqMapper.selectAcqListByStatus(status);
    }

    @Override
    public List<Acq> selectAcqListByApp(String type) {
        // TODO Auto-generated method stub
        return acqMapper.selectAcqListByApp(type);
    }

    /**
     * 消费接口
     *
     * @throws Exception
     */
    @Override
    public AjaxResult GaungGuQuickPay(JSONObject jsonParam) throws Exception {
        // 获取商户信息
        Merchant m = merchantMapper.selectMerchantById(jsonParam.getString("merId"));
        String redisKey = "gaungGuPay:" + m.getId();
        String pay = RedisPoolUtil.get(redisKey);
        if (StringUtils.isNotEmpty(pay)) {
            return AjaxResult.error(1, "短时间内不要频繁操作，以免对您的信用卡造成影响!");
        }
        RedisPoolUtil.setex(redisKey, "1", 60);
        String orderNo = "";
        // 密码支付
        String paypwd = jsonParam.getString("paypwd");
        Acq acq = acqMapper.selectAcqById(jsonParam.getString("acqId"));
        if (acq.getPaymentType().equals(0) && !Md5Utils.encrypt2MD5(paypwd).equals(m.getPaymentPwd())) {
            return AjaxResult.error("支付密码错误");
        }
        orderNo = StringUtils.createNum();
        // 获取通道信息
        BigDecimal moeny = jsonParam.getBigDecimal("orderAmount");
        // 判断消费是否小于通道的最小消费额
        if (acq.getMin().compareTo(moeny) == 1) {
            return AjaxResult.error("消费金额需大于" + acq.getMin().setScale(0, BigDecimal.ROUND_UP) + ",请调整金额");
        }
        // 判断消费是否大于通道的最大消费额
        if (acq.getMax().compareTo(moeny) == -1) {
            return AjaxResult.error("消费金额需小于" + acq.getMax().setScale(0, BigDecimal.ROUND_UP) + ",请调整金额");
        }
        // 获取平台费率
        String rateStr = "";
        try {
            // 从redis中取
            rateStr = RedisPoolUtil.get("rate");
        } catch (Exception e) {
            rateStr = "nil";
        }
        if (rateStr == null || "".equals(rateStr) || "nil".equals(rateStr)) {
            // 查询全局配置获取平台费率
            SystemConfig config = configMapper.selectSystemConfigByConfigCode(SystemConfigCode.RATE.getCode());
            try {
                // 保存到缓存中
                RedisPoolUtil.setex("rate", config.getConfigValue(), 86400);
            } catch (Exception e) {
            }
            rateStr = config.getConfigValue();
        }
        // 费率配置转json对象
        JSONObject rateJson = JSONObject.parseObject(rateStr);
        // 笔数费
        BigDecimal pro = BigDecimal.ZERO;
        // 费率
        BigDecimal rate = BigDecimal.ZERO;
        rate = new BigDecimal(rateJson.getString("wk").split("\\+")[0]);
        pro = new BigDecimal(rateJson.getString("wk").split("\\+")[1]);
        /** 根据信用卡id查询信用卡信息 */
        CreditCardVo creditCardId = merchantIncreaseLimitMapper.selectCardVoById(jsonParam.getString("creditCardId"));
        /** 调用三方消费接口 */
        PaymentOrderVO po = new PaymentOrderVO();
        po.setPaymentType(0);
        // 公司id
        po.setAcqCode(acq.getAcqCode());
        // 上游用户编号
        if (StringUtils.isNotEmpty(m.getAcqMerchantNo())) {
            po.setUserId(m.getAcqMerchantNo());
        }
        // 订单号
        po.setOrderNo(orderNo);
        // 金额
        po.setAmountMoney(moeny);
        // 费率
        po.setRate(rate.multiply(new BigDecimal("100")).toString());
        // 笔数费
        po.setPro(pro);
        // 卡号
        po.setCreditNumber(creditCardId.getBankAccount());
        if (StringUtils.isNotEmpty(m.getIdCardNumber())) {
            // 身份证
            po.setIdCardNo(m.getIdCardNumber());
        }
        // 手机号
        po.setMobile(creditCardId.getBankPhone());
        // 信用卡背面后三位
        po.setMccCode(creditCardId.getCvn());
        // 有效期
        po.setExpired(creditCardId.getExpdate());
        // 姓名/银行卡户名
        po.setBankAccountName(m.getMerchantCnName());
        // 交易地区
        po.setRegion(jsonParam.getString("region"));
        // 交易终端ip
        po.setTrxSourceIp(jsonParam.getString("ip"));
        // 银行卡代码
        po.setBankCode(creditCardId.getBankCode());
        // 卡类型1借记卡2贷记卡
        po.setCardType("2");
        po.setMccCode(creditCardId.getCvn());
        PaymentOrder p = new PaymentOrder();
        // 消费成功
        String orderId = StringUtils.randomUUID();
        p.setId(orderId);
        // 订单号
        p.setOrderNo(po.getOrderNo());
        // ip
        p.setIp(jsonParam.getString("ip"));
        // 通道id
        p.setAcqId(jsonParam.getString("acqId"));
        // 渠道编号
        p.setAcqCode(acq.getAcqCode());
        // 渠道名称
        p.setAcqName(acq.getAcqName());
        // 清分状态默认未清分
        p.setClearingStatus(0);
        // 无卡快捷
        p.setOrderType(0);
        // 成本
        BigDecimal costRate = moeny
                .multiply(acq.getCostRate().divide(new BigDecimal(100)).setScale(4, BigDecimal.ROUND_UP));
        // 成本手续费
        p.setCostRateMoney(costRate);
        // 商户本地id
        p.setMerchantId(jsonParam.getString("merId"));
        // 商户名称
        p.setMerchantName(m.getMerchantCnName());
        // 信用卡号
        p.setCreditNumber(creditCardId.getBankAccount());
        // 银行卡名称
        p.setBankName(creditCardId.getBankName());
        BigDecimal rateMoney = moeny.multiply(rate).setScale(2, BigDecimal.ROUND_UP);
        // 手续费金额
        p.setRateMoney(rateMoney);
        // 订单创建时间
        p.setCreateTime(new Date());
        p.setOrderStatus(0);
        // 金额
        p.setAmountMoney(moeny);
        // 收益
        p.setProfitMoney(rateMoney.subtract(costRate));
        // ip
        p.setIp(jsonParam.getString("ip"));
        if (acq.getPaymentType().equals(1)) {
            p.setProfitMoney(p.getProfitMoney().add(pro.subtract(acq.getDrawRate())));
            p.setOrderType(11);
            p.setToCardBank(m.getBankAccount());
            p.setToCardNumber(m.getBankName());
            po.setToBankCardNo(m.getBankAccount());
            po.setPaymentType(4);
            po.setToBankChannelNo(m.getBankDot());
            po.setToBankCode(m.getBankCode());
            po.setToBankName(m.getBankName());
        }
        paymentOrderMapper.insertPaymentOrder(p);
        PaymentOrder pNow = new PaymentOrder();
        try {
            JSONObject json = GuangGuUtil.payment(po);
            if ("SUCCESS".equals(json.getString("ret_code")) && "YQB000000".equals(json.getString("res_code"))) {
                pNow.setId(orderId);
                pNow.setCompleteTime(new Date());
                pNow.setAcqReturnCode(json.getString("res_code"));
                pNow.setAcqReturnMsg(json.getString("res_msg"));
                if ("2".equals(json.getString("status"))) {
                    paymentOrderMapper.updatePaymentOrder(pNow);
                    if (acq.getPaymentType().equals(0)) {
                        return AjaxResult.success("交易处理中");
                    } else {
                        return AjaxResult.successAndData(json.getString("url"), json.getString("url"));
                    }
                } else {
                    pNow.setOrderStatus(2);
                    paymentOrderMapper.updatePaymentOrder(pNow);
                    return AjaxResult.error(1, json.getString("res_msg"));
                }
            } else {
                pNow.setOrderStatus(2);
                paymentOrderMapper.updatePaymentOrder(pNow);
                return AjaxResult.error(1, json.getString("res_msg"));
            }
        } catch (Exception e) {
            pNow.setOrderStatus(2);
            pNow.setAcqReturnCode("消费上送json解析");
            pNow.setAcqReturnMsg("消费上送json解析失败");
            paymentOrderMapper.updatePaymentOrder(pNow);
            return AjaxResult.error(3, "交易失败。请重新发起");
        }
    }

    /**
     * 出款
     *
     * @throws Exception
     */
    @Override
    public AjaxResult guangGuOut(PaymentOrder order, String merId) {
        // 获取商户信息
        Merchant m = merchantMapper.selectMerchantById(order.getMerchantId());
        String orderid = StringUtils.randomUUID();
        order.setId(orderid);
        order.setOrderNo(StringUtils.createNum());
        // 根据渠道id查询渠道信息
        Acq acq = acqMapper.selectAcqById(order.getAcqId());
        // 获取平台费率配置
        String rateStr = "";
        try {
            rateStr = RedisPoolUtil.get("rate");
        } catch (Exception e) {
            rateStr = "nil";
        }
        if (rateStr == null || "".equals(rateStr) || "nil".equals(rateStr)) {
            SystemConfig config = configMapper.selectSystemConfigByConfigCode("rate");
            try {
                RedisPoolUtil.setex("rate", config.getConfigValue(), 86400);
            } catch (Exception e) {
            }
            rateStr = config.getConfigValue();
        }
        // 费率配置转json对象
        JSONObject rateJson = JSONObject.parseObject(rateStr);
        // 笔数费
        BigDecimal pro = BigDecimal.ZERO;
        // 费率
        BigDecimal rate = BigDecimal.ZERO;
        pro = new BigDecimal(rateJson.getString("wk").split("\\+")[1]);
        // 待回调
        order.setOrderStatus(0);
        order.setCreateTime(new Date());
        // 订单类型 无卡出款
        order.setOrderType(3);
        // 计算消费实际消费钱
        BigDecimal money = order.getAmountMoney().subtract(order.getRateMoney().setScale(2, BigDecimal.ROUND_DOWN));
        order.setAmountMoney(money);
        order.setClearingStatus(1);
        // 成本手续费
        order.setCostRateMoney(acq.getDrawRate());
        // 实际手续费
        order.setRateMoney(pro);
        // 收益
        order.setProfitMoney(pro.subtract(acq.getDrawRate()));
        // 订单创建时间
        order.setCompleteTime(new Date());
        // 卡号
        order.setCreditNumber(m.getBankAccount());
        // 银行卡名称
        order.setBankName(m.getBankName());
        /** 生成订单 */
        paymentOrderMapper.insertPaymentOrder(order);
        try {
            /** 调用三方接口 */
            PaymentOrderVO pa = new PaymentOrderVO();
            // 0 无卡 1养卡
            pa.setPaymentType(0);
            // 公司id
            pa.setAcqCode(order.getAcqCode());
            // 订单号
            pa.setOrderNo(order.getOrderNo());
            // 用户id
            pa.setUserId(m.getAcqMerchantNo());
            // 账户名称
            pa.setBankAccountName(m.getMerchantCnName());
            // 银行卡号
            pa.setCreditNumber(m.getBankAccount());
            // 银行卡代码
            pa.setBankCode(m.getBankCode());
            // 银行名称
            pa.setBankName(m.getBankName());
            // 证件号
            pa.setIdCardNo(m.getIdCardNumber());
            // 手机号
            pa.setMobile(m.getReservePhone());
            // 金额
            pa.setAmountMoney(order.getAmountMoney());
            // 笔数费
            pa.setPro(pro);
            // 费率
            pa.setRate(rate.toString());
            // ip
            pa.setTrxSourceIp(order.getIp());
            // 个人账户
            pa.setBankType("1");
            // 借记卡
            pa.setCardType("1");
            JSONObject json = GuangGuUtil.repayment(pa);
            // 判断调用接口是否成功
            if ("SUCCESS".equals(json.getString("ret_code"))) {
                if ("YQB000000".equals(json.getString("res_code"))) {
                    order.setAcqReturnCode(json.getString("res_code"));
                    order.setAcqReturnMsg(json.getString("res_msg"));
                    order.setCompleteTime(new Date());
                    order.setAcqOrderNo(json.getString("seria_no"));
                    // 订单状态
                    if ("1".equals(json.getString("status"))) {
                        // 成功
                        order.setOrderStatus(1);
                    } else if ("2".equals(json.getString("status"))) {
                        // 处理中
                        order.setOrderStatus(0);
                    } else {
                        // 失败
                        order.setOrderStatus(2);
                    }
                    paymentOrderMapper.updatePaymentOrder(order);
                    return AjaxResult.success(json.getString("res_msg"));
                } else {
                    order.setOrderStatus(2);
                    order.setAcqReturnCode(json.getString("res_code"));
                    order.setAcqReturnMsg(json.getString("res_msg"));
                    paymentOrderMapper.updatePaymentOrder(order);
                    return AjaxResult.error(1, json.getString("res_msg"));
                }
            } else {
                order.setOrderStatus(2);
                order.setAcqReturnCode(json.getString("res_code"));
                order.setAcqReturnMsg(json.getString("res_msg"));
                paymentOrderMapper.updatePaymentOrder(order);
                return AjaxResult.error(1, "交易失败。请重新发起");
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            log.error("出款异常=" + e.toString());
            order.setOrderStatus(2);
            order.setAcqReturnCode("444");
            order.setAcqReturnMsg("出款异常：" + e.toString());
            paymentOrderMapper.updatePaymentOrder(order);
            return AjaxResult.error(1, "出款异常：" + e.toString());
        }
    }

    /**
     *
     */
    @Override
    public AjaxResult paymentOut(String merId, BigDecimal txnAmt, String trxSourceIp, String payPwd) {
        String key = "lock:payOut:" + merId;
        String suo = RedisPoolUtil.get(key);
        if (suo != null && suo.equals("1")) {
            return AjaxResult.error(1, "请勿重复提交");
        }
        RedisPoolUtil.setex(key, "1", 300);
        if (StringUtils.isEmpty(merId) || StringUtils.isEmpty(trxSourceIp) || txnAmt == null
                || StringUtils.isEmpty(payPwd)) {
            RedisPoolUtil.del(key);
            return AjaxResult.error(1, "缺失参数");
        }
        if (txnAmt.compareTo(new BigDecimal(0)) <= 0 || txnAmt.compareTo(new BigDecimal(3)) == -1) {
            RedisPoolUtil.del(key);
            return AjaxResult.error(2, "提现金额不能小于3元");
        }

        Merchant mer = merchantMapper.selectMerchantById(merId);
        if (mer == null) {
            return AjaxResult.error(3, "该用户不存在");
        }
        MerchantWallet merchantWallet = merchantWalletMapper.selectMerchantWalletByMerId(merId);
        if (merchantWallet.getTotalMoney().compareTo(txnAmt) == -1) {
            RedisPoolUtil.del(key);
            return AjaxResult.error(4, "提现金额大于余额");
        }
        if (!mer.getPaymentPwd().equals(Md5Utils.encrypt2MD5(payPwd))) {
            RedisPoolUtil.del(key);
            return AjaxResult.error(4, "支付密码输入不正确");
        }
        if (mer.getLevel() < 6 || mer.getIsCompany().equals("10B") ||
                mer.getIsCompany().equals("10D")) {
            // 手动升级提现金额限制
            String withdrawalLimit = "";
            try {
                // 从redis中取
                withdrawalLimit = RedisPoolUtil.get("withdrawalLimit");
            } catch (Exception e) {
                withdrawalLimit = "nil";
            }
            if (withdrawalLimit == null || "".equals(withdrawalLimit) || "nil".equals(withdrawalLimit)) {
                SystemConfig config = configMapper.selectSystemConfigByConfigCode("withdrawalLimit");
                // 保存到缓存中
                RedisPoolUtil.set("withdrawalLimit", config.getConfigValue());
                withdrawalLimit = config.getConfigValue();
            }
            BigDecimal withdrawalLimitB = new BigDecimal(withdrawalLimit);
            if (txnAmt.add(merchantWallet.getCashIntegral()).compareTo(withdrawalLimitB) >= 1) {
                return AjaxResult.error(10, "提现受限，详情联系客服。");
            }
        }
        PaymentOrder paymentOrder = paymentOrderMapper.selectPaymentOrderPaymentOut(mer.getId());
        if (paymentOrder != null && paymentOrder.getOrderStatus().equals(0)) {
            RedisPoolUtil.del("payOut" + merId);
            return AjaxResult.error(4, "提现流水清算中，请稍后重试！");
        }
        log.info("用户{" + mer.getMerchantCnName() + "}[" + mer.getId() + "]提现:" + txnAmt + "元！");
        Acq acq = acqMapper.selectAcqById("F8C77A7E92DA4A75A6FD880A7072EE1A");
        // 订单预处理
        PaymentOrder order = saveOrder(mer, txnAmt, acq);
        // 提现记录预处理
        String moneyChangeId = saveMoneyChange(mer.getId(), order.getId(), txnAmt);
        // 参数封装处理
        PaymentOrderVO orderNow = savePaymentOrderVO(order, acq, mer, trxSourceIp);
        MoneyChange moneyChange = new MoneyChange();
        moneyChange.setId(moneyChangeId);
        PaymentOrder p = new PaymentOrder();
        p.setId(order.getId());
        try {
            // 提现预处理
            merchantWalletMapper.withdrawalPretreatment(mer.getId(), txnAmt);
            JSONObject json = GuangGuUtil.repaymentMch(orderNow);
            if (json == null) {
                // 请求失败
                merchantWalletMapper.withdrawalFail(mer.getId(), txnAmt);
                moneyChange.setStatus("10D");
                moneyChangeMapper.updateMoneyChange(moneyChange);
                p.setOrderStatus(2);
                p.setAcqReturnCode("2");
                p.setAcqReturnMsg("请求失败");
                paymentOrderMapper.updatePaymentOrder(p);
                RedisPoolUtil.del(key);
                return AjaxResult.error(5, "提现请求失败,请重试");
            }
            p.setAcqReturnCode(json.getString("res_code"));
            p.setAcqReturnMsg(json.getString("res_msg"));
            if ("SUCCESS".equals(json.getString("ret_code")) && "YQB000000".equals(json.getString("res_code"))) {
                // 1：成功2:处理中 3:失败
                // 4:清算异常
                // 0:预处理
                // 订单状态（0处理中1成功2失败3已补单 9回 ）
                if ("2".equals(json.getString("status"))) {
                    RedisPoolUtil.del(key);
                    return AjaxResult.error(0, "提现处理中");
                } else {
                    RedisPoolUtil.del(key);
                    merchantWalletMapper.withdrawalFail(mer.getId(), txnAmt);
                    moneyChange.setStatus("10D");
                    moneyChangeMapper.updateMoneyChange(moneyChange);
                    return AjaxResult.error(1, json.getString("res_msg"));
                }
            } else {
                RedisPoolUtil.del(key);
                merchantWalletMapper.withdrawalFail(mer.getId(), txnAmt);
                p.setOrderStatus(2);
                paymentOrderMapper.updatePaymentOrder(p);
                moneyChange.setStatus("10D");
                moneyChangeMapper.updateMoneyChange(moneyChange);
                return AjaxResult.error(5, json.getString("res_msg"));
            }
        } catch (Exception e) {
            RedisPoolUtil.del("payOut" + merId);
            merchantWalletMapper.withdrawalFail(mer.getId(), txnAmt);
            log.error("提现异常{}", e);
            p.setOrderStatus(2);
            p.setAcqReturnCode("2");
            p.setAcqReturnMsg("处理异常");
            paymentOrderMapper.updatePaymentOrder(p);
            moneyChange.setStatus("10D");
            moneyChangeMapper.updateMoneyChange(moneyChange);
            return AjaxResult.error(5, "提现处理异常,请联系客服");
        }

    }

    /**
     * 提现参数封装
     *
     * @param order
     * @param acq
     * @return
     */
    private PaymentOrderVO savePaymentOrderVO(PaymentOrder order, Acq acq, Merchant mer, String trxSourceIp) {
        BigDecimal pro = new BigDecimal("2");
        PaymentOrderVO orderVO = new PaymentOrderVO();
        orderVO.setAcqCode(acq.getAcqCode());
        orderVO.setOrderNo(order.getOrderNo());
        orderVO.setUserId(mer.getAcqMerchantNo());
        orderVO.setBankName(mer.getBankName());
        orderVO.setBankType("1");
        orderVO.setBankAccountName(mer.getMerchantCnName());
        orderVO.setBankCode(mer.getBankCode());
        orderVO.setCreditNumber(mer.getBankAccount());
        orderVO.setCardType("1");
        orderVO.setIdCardNo(mer.getIdCardNumber());
        orderVO.setMobile(mer.getReservePhone());
        orderVO.setMccCode("");
        orderVO.setExpired("");
        orderVO.setTrxSourceIp(trxSourceIp);
        orderVO.setAmountMoney(order.getAmountMoney().subtract(order.getRateMoney()).add(pro));
        orderVO.setRate("");
        orderVO.setPro(pro);
        orderVO.setMemo("用户提现");
        return orderVO;
    }

    /**
     * 保存提现记录
     *
     * @return
     */
    private String saveMoneyChange(String merId, String orderId, BigDecimal txnAmt) {
        MoneyChange moneyChange = new MoneyChange();
        String id = StringUtils.createNum();
        moneyChange.setId(id);
        moneyChange.setMoneyType(MoneyTypeStatus.F.getCode());
        moneyChange.setTrxAmt(txnAmt);
        moneyChange.setUserId(merId);
        moneyChange.setPaymentOrderId(orderId);
        moneyChange.setStatus("10A");
        moneyChange.setCreateTime(new Date());
        moneyChangeMapper.insertMoneyChange(moneyChange);
        return id;
    }

    /**
     * 预处理 保存订单信息
     *
     * @param mer
     * @param txnAmt
     */
    private PaymentOrder saveOrder(Merchant mer, BigDecimal txnAmt, Acq acq) {
        PaymentOrder p = new PaymentOrder();
        String orderId = StringUtils.randomUUID();
        String orderNo = StringUtils.createNum();
        p.setId(orderId);
        p.setOrderNo(orderNo);
        p.setMerchantId(mer.getId());
        p.setMerchantName(mer.getMerchantCnName());
        p.setOrderStatus(0);
        p.setOrderType(5);
        p.setAcqId(acq.getId());
        p.setAcqName(acq.getAcqName());
        p.setAcqCode(acq.getAcqCode());
        p.setCreditNumber(mer.getBankAccount());
        p.setBankName(mer.getBankName());
        p.setAmountMoney(txnAmt);
        p.setCostRateMoney(new BigDecimal("1"));
        p.setRateMoney(new BigDecimal("2")
                .add(txnAmt.multiply(BigDecimal.valueOf(0.06)).setScale(3, BigDecimal.ROUND_DOWN)));
        p.setProfitMoney(new BigDecimal("0"));
        p.setClearingStatus(1);
        paymentOrderMapper.insertPaymentOrder(p);
        return p;
    }

    /**
     * 查询通道信息
     *
     * @param code 通道编码 (公司ID)
     * @return 通道信息
     */
    @Override
    public Acq selectAcqByCode(String code) {
        return acqMapper.selectAcqByCode(code);
    }

    /**
     * 查询信用卡通道绑定中间信息
     *
     * @param acqId  通道ID
     * @param bankId 银行ID
     * @return
     */
    @Override
    public AcqBind selectAcqBindByBankIdAndAcqId(String acqId, String bankId) {
        return acqBindMapper.selectAcqBindByBankIdAndAcqId(acqId, bankId);
    }

    @Override
    public AjaxResult quickPay(String merchanId, String bankId, BigDecimal orderAmount, String ip, String region,
                               String deviceId) {
        // TODO Auto-generated method stub
        if (orderAmount.compareTo(new BigDecimal(1000)) == -1) {
            return null;
        } else {
            JSONObject json = new JSONObject();
            json.put("merId", merchanId);
            json.put("orderAmount", orderAmount);
            json.put("creditCardId", bankId);
            json.put("region", region);
            json.put("ip", ip);
            try {
                return GaungGuQuickPay(json);
            } catch (Exception e) {
                log.error("无卡异常：{}", e);
                return AjaxResult.error(3, "交易失败。请重新发起");
            }
        }
    }

    /**
     * 无卡收款 通道信息
     *
     * @param orderAmount
     * @param bankId
     * @param cvn
     * @param expdate
     * @param bankPhone
     * @param bankAccount
     * @param idCardNumber
     * @param bankAccountName
     * @return
     */
    @Override
    public AjaxResult getAcq(BigDecimal orderAmount, String bankId, String bankAccountName, String idCardNumber,
                             String bankAccount, String bankPhone, String expdate, String cvn) {
        List<AcqBind> bindList = acqBindMapper.selectByCardId(bankId);
        if (bindList == null || bindList.size() <= 0) {
            return AjaxResult.error(1, "未找寻到通道签约信息，请先开通道");
        }
        String acqIds = "";
        for (AcqBind acqBind : bindList) {
            acqIds += acqBind.getAcqId() + ",";
        }
        acqIds = acqIds.substring(0, acqIds.length() - 1);
        Acq a = null;
        if (orderAmount.compareTo(new BigDecimal(1000)) == -1) {
            List<Acq> acqList = acqMapper.selectAcqListByIsSmall(1, acqIds);
            if (acqList.size() == 0) {
                a = null;
            } else if (acqList.size() > 0) {
                Integer weightSum = 0;
                Random random = new Random();
                for (Acq acq : acqList) {
                    weightSum += acq.getWeight();
                }
                if (weightSum.equals(0)) {
                    a = null;
                } else {
                    Integer n = random.nextInt(weightSum); // n in [0,
                    // weightSum)
                    Integer m = 0;
                    for (Acq acq : acqList) {
                        if (m <= n && n < m + acq.getWeight()) {
                            a = acq;
                            break;
                        }
                        m += acq.getWeight();
                    }
                }
            }
        }
        if (a == null) {
            List<Acq> acqList = acqMapper.selectAcqListByIsSmall(0, acqIds);
            if (acqList.size() > 0) {
                Integer weightSum = 0;
                Random random = new Random();
                for (Acq acq : acqList) {
                    weightSum += acq.getWeight();
                }
                if (weightSum.equals(0)) {
                    a = null;
                } else {
                    Integer n = random.nextInt(weightSum); // n in [0,
                    // weightSum)
                    Integer m = 0;
                    for (Acq acq : acqList) {
                        if (m <= n && n < m + acq.getWeight()) {
                            a = acq;
                            break;
                        }
                        m += acq.getWeight();
                    }
                }
            }
        }
        if (a != null) {
            String rateStr = "";
            try {
                rateStr = RedisPoolUtil.get("rate");
            } catch (Exception e) {
                rateStr = "nil";
            }
            if (rateStr == null || "".equals(rateStr) || "nil".equals(rateStr)) {
                SystemConfig config = configMapper.selectSystemConfigByConfigCode("rate");
                try {
                    RedisPoolUtil.setex("rate", config.getConfigValue(), 86400);
                } catch (Exception e) {
                    // TODO: handle exception
                }
                rateStr = config.getConfigValue();
            }
            JSONObject rateJson = JSONObject.parseObject(rateStr);

            // 笔数费
            BigDecimal pro = new BigDecimal(rateJson.getString("wk").split("\\+")[1]);
            // 费率
            BigDecimal rate = new BigDecimal(rateJson.getString("wk").split("\\+")[0]);
            BigDecimal vipPro = new BigDecimal(rateJson.getString("vipWk").split("\\+")[1]);
            BigDecimal vipRate = new BigDecimal(rateJson.getString("vipWk").split("\\+")[0]);
            BigDecimal rateMoney = orderAmount.multiply(rate).add(pro).setScale(2, BigDecimal.ROUND_UP);
            BigDecimal vipMoney = orderAmount.multiply(vipRate).add(vipPro).setScale(2, BigDecimal.ROUND_UP);
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("arrivalMoney", orderAmount.subtract(rateMoney));
            map.put("smoney", rateMoney.subtract(vipMoney).setScale(2, BigDecimal.ROUND_DOWN));
            map.put("acq", a);
            return AjaxResult.successAndData("成功", map);
        } else {
            return AjaxResult.error(1, "未找寻到通道签约信息，请先开通道");
        }
    }

    /********************************** 辅助方法 ***********************************/

    public MerchantIncreaseLimit merchantIncreaseLimit(JSONObject jsonParam) {
        MerchantIncreaseLimit mer = new MerchantIncreaseLimit();
        if (StringUtils.isNotEmpty(jsonParam.getString("companyId"))) {
            // 公司编号
            mer.setCompanyId(jsonParam.getString("companyId"));
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("userId"))) {
            // 用户编号
            mer.setUserId(jsonParam.getString("userId"));
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("bankAccountName"))) {
            // 姓名/银行卡账户名
            mer.setBankAccountName(jsonParam.getString("bankAccountName"));
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("bankAccount"))) {
            // 信用卡号
            mer.setBankAccount(jsonParam.getString("bankAccount"));
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("idCardNumber"))) {
            // 身份证号码
            mer.setIdCardNumber(jsonParam.getString("idCardNumber"));
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("bankPhone"))) {
            // 预留的手机号
            mer.setBankPhone(jsonParam.getString("bankPhone"));
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("bankName"))) {
            // 银行名称
            IssBank issBank = issBankMapper.selectIssBankByName(jsonParam.getString("bankName"));
            if (StringUtils.isNotNull(issBank)) {
                // 银行代码
                mer.setBankCode(issBank.getBankCode());
            }
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("cvn"))) {
            // 信用卡背后三位
            mer.setCvn(jsonParam.getString("cvn"));
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("expDate"))) {
            // 有效期
            mer.setExpdate(
                    jsonParam.getString("expDate").substring(2, 4) + jsonParam.getString("expDate").substring(0, 2));
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("smsCode"))) {
            // 短信验证吗
            mer.setSmsCode(jsonParam.getString("smsCode"));
        }
        if (StringUtils.isNotEmpty(jsonParam.getString("callerIp"))) {
            // 调用段ip地址
            mer.setTrxSourceIp(jsonParam.getString("callerIp"));
        }
        return mer;
    }

    /**
     * | 后台查询订单出款接口
     *
     * @param order
     * @param merId
     * @return
     */
    @Override
    public Map<String, String> htguangGuOut(PaymentOrder order, String merId) {
        // 返回参数
        Map<String, String> map = new HashMap<>();
        // 获取商户信息
        Merchant m = merchantMapper.selectMerchantById(order.getMerchantId());
        String orderid = StringUtils.randomUUID();
        order.setId(orderid);
        order.setOrderNo(StringUtils.createNum());
        // 根据渠道id查询渠道信息
        Acq acq = acqMapper.selectAcqById(order.getAcqId());
        // 获取平台费率配置
        String rateStr = "";
        try {
            rateStr = RedisPoolUtil.get("rate");
        } catch (Exception e) {
            rateStr = "nil";
        }
        if (rateStr == null || "".equals(rateStr) || "nil".equals(rateStr)) {
            SystemConfig config = configMapper.selectSystemConfigByConfigCode("rate");
            try {
                RedisPoolUtil.setex("rate", config.getConfigValue(), 86400);
            } catch (Exception e) {
                // TODO: handle exception
            }
            rateStr = config.getConfigValue();
        }
        // 费率配置转json对象
        JSONObject rateJson = JSONObject.parseObject(rateStr);
        // 笔数费
        BigDecimal pro = BigDecimal.ZERO;
        // 费率
        BigDecimal rate = BigDecimal.ZERO;
        pro = new BigDecimal(rateJson.getString("wk").split("\\+")[1]);
        // 待回调
        order.setOrderStatus(0);
        order.setCreateTime(new Date());
        // 订单类型 无卡出款
        order.setOrderType(3);
        // 计算消费实际消费钱
        BigDecimal money = order.getAmountMoney().subtract(order.getRateMoney().setScale(2, BigDecimal.ROUND_DOWN));
        order.setAmountMoney(money);
        order.setClearingStatus(1);
        // 成本手续费
        order.setCostRateMoney(acq.getDrawRate());
        // 实际手续费
        order.setRateMoney(pro);
        // 收益
        order.setProfitMoney(pro.subtract(acq.getDrawRate()));
        // 订单创建时间
        order.setCompleteTime(new Date());
        // 卡号
        order.setCreditNumber(m.getBankAccount());
        // 银行卡名称
        order.setBankName(m.getBankName());
        try {
            /** 调用三方接口 */
            PaymentOrderVO pa = new PaymentOrderVO();
            // 0 无卡 1养卡
            pa.setPaymentType(0);
            // 公司id
            pa.setAcqCode(order.getAcqCode());
            // 用户id
            pa.setUserId(m.getAcqMerchantNo());
            // 订单号
            pa.setOrderNo(order.getOrderNo());
            // 账户名称
            pa.setBankAccountName(m.getMerchantCnName());
            // 银行卡号
            pa.setCreditNumber(m.getBankAccount());
            // 银行卡代码
            pa.setBankCode(m.getBankCode());
            // 银行名称
            pa.setBankName(m.getBankName());
            // 证件号
            pa.setIdCardNo(m.getIdCardNumber());
            // 手机号
            pa.setMobile(m.getReservePhone());
            // 金额
            pa.setAmountMoney(order.getAmountMoney());
            // 笔数费
            pa.setPro(pro);
            // 费率
            pa.setRate(rate.toString());
            // ip
            pa.setTrxSourceIp(order.getIp());
            // 个人账户
            pa.setBankType("1");
            // 借记卡
            pa.setCardType("1");
            JSONObject json = GuangGuUtil.repayment(pa);
            // 判断调用接口是否成功
            if ("SUCCESS".equals(json.getString("ret_code"))) {
                if ("YQB000000".equals(json.getString("res_code"))) {
                    order.setAcqReturnCode(json.getString("res_code"));
                    order.setCompleteTime(new Date());
                    order.setAcqReturnMsg(json.getString("res_msg"));
                    order.setAcqOrderNo(json.getString("seria_no"));
                    // 订单状态
                    if ("1".equals(json.getString("status"))) {
                        // 成功
                        order.setOrderStatus(1);
                        paymentOrderMapper.insertPaymentOrder(order);
                    } else if ("2".equals(json.getString("status"))) {
                        // 处理中
                        order.setOrderStatus(0);
                        paymentOrderMapper.insertPaymentOrder(order);
                    }
                    map.put("code", json.getString("res_code"));
                    map.put("msg", json.getString("res_msg"));
                    return map;
                } else {
                    map.put("code", json.getString("res_code"));
                    map.put("msg", json.getString("res_msg"));
                    return map;
                }
            } else {
                map.put("code", json.getString("ret_code"));
                map.put("msg", "出款失败,请重新发起");
                return map;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            log.error("出款异常=" + e.toString());
            map.put("code", "444");
            map.put("msg", "出款异常");
            return map;
        }
    }
}
